package org.example.createnewclass;

import javassist.*;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) throws IOException, CannotCompileException, NotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        ClassPool pool = ClassPool.getDefault();
        // 定义一个新类
        CtClass point = pool.makeClass("Point");

        // 添加字段
        // 首先添加字段 private float dx;
        CtField dxField = new CtField(pool.getCtClass("float"), "dx", point);
        dxField.setModifiers(Modifier.PRIVATE);
        point.addField(dxField);

        // 其次添加字段 private float dy;
        CtField dyField = new CtField(pool.getCtClass("float"), "dy", point);
        dyField.setModifiers(Modifier.PRIVATE);
        point.addField(dyField);

        // 为字段dx和dy添加getXXX和setXXX方法
        point.addMethod(CtNewMethod.getter("getDx", dxField));
        point.addMethod(CtNewMethod.setter("setDx", dxField));
        point.addMethod(CtNewMethod.getter("getDy", dyField ));
        point.addMethod(CtNewMethod.setter("setDy", dyField));

        //添加无参构造器
        CtConstructor ctConstructor1 = new CtConstructor(new CtClass[]{}, point);
        point.addConstructor(ctConstructor1);


        //添加有参构造函数
        CtConstructor ctConstructor = new CtConstructor(new CtClass[]{pool.get("float"), pool.get("float")}, point);
        //为构造函数设置函数体
        StringBuffer buffer = new StringBuffer();
        buffer.append("{\n")
                .append("$0.dx = $1;\n")
                .append("$0.dy = $2;\n")
                .append("}");
        ctConstructor.setBody(buffer.toString());
        point.addConstructor(ctConstructor);

        //添加一个方法
        CtMethod ctMethod = CtNewMethod.make("public void hello(){\nSystem.out.println(\"hello\");\n}", point);
        point.addMethod(ctMethod);

        // 添加自定义方法
        CtMethod ctMethod2 = new CtMethod(CtClass.voidType, "printInfo", new CtClass[]{}, point);
        // 为自定义方法设置修饰符
        ctMethod2.setModifiers(Modifier.PUBLIC);
        //为自定义方法设置函数体
        StringBuffer buffer1 = new StringBuffer();
        buffer1.append("{\nSystem.out.println(\"begin!\");\n")
                .append("System.out.println($0.dx);\n")
                .append("System.out.println($0.dy);\n")
                .append("System.out.println(\"over!\");\n")
                .append("}");
        ctMethod2.setBody(buffer1.toString());
        point.addMethod(ctMethod2);

        // 输出类中声明的方法
        CtMethod[] declaredMethods = point.getDeclaredMethods();
        for(CtMethod ctMethod1 : declaredMethods){
            System.out.println(ctMethod1.getMethodInfo());
            System.out.println(ctMethod1.getName());
            
        }

//        Object obj = point.toClass().newInstance();
//        obj.getClass().getMethod("hello", new Class[]{}).invoke(obj, new Object[]{});

        // 将字节码文件 写入某个特定的目录
        point.writeFile("F:\\javacode\\javassistDemo\\javassistDemo\\src\\main\\java\\org\\example\\createnewclass");
    }
}
